package com.vaadin.incubator.bugrap;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Random;

import com.vaadin.incubator.bugrap.model.facade.FacadeFactory;
import com.vaadin.incubator.bugrap.model.facade.FacadeUtil;
import com.vaadin.incubator.bugrap.model.projects.Project;
import com.vaadin.incubator.bugrap.model.projects.ProjectVersion;
import com.vaadin.incubator.bugrap.model.reports.Comment;
import com.vaadin.incubator.bugrap.model.reports.CommentType;
import com.vaadin.incubator.bugrap.model.reports.Report;
import com.vaadin.incubator.bugrap.model.reports.ReportResolution;
import com.vaadin.incubator.bugrap.model.reports.ReportStatus;
import com.vaadin.incubator.bugrap.model.reports.ReportType;
import com.vaadin.incubator.bugrap.model.users.Reporter;

public class DBTools {

	public static boolean drop() {
		System.out.println("===== DROPPING DATABASE ========");

		// Comments
		System.out.print("* Removing all comments... ");
		List<Comment> comments = FacadeFactory.getFacade().list(Comment.class);
		FacadeFactory.getFacade().deleteAll(comments);
		System.out.println("Done.");

		// Reports
		System.out.print("* Removing all reports... ");
		List<Report> reports = FacadeFactory.getFacade().list(Report.class);
		FacadeFactory.getFacade().deleteAll(reports);
		System.out.println("Done.");

		// Report versions
		System.out.print("* Removing all project versions... ");
		List<ProjectVersion> versions = FacadeFactory.getFacade().list(
				ProjectVersion.class);
		FacadeFactory.getFacade().deleteAll(versions);
		System.out.println("Done.");

		// Projects
		System.out.print("* Removing all projects... ");
		List<Project> projects = FacadeFactory.getFacade().list(Project.class);
		FacadeFactory.getFacade().deleteAll(projects);
		System.out.println("Done.");

		// Reporters
		System.out.print("* Removing all users... ");
		List<Reporter> users = FacadeFactory.getFacade().list(Reporter.class);
		FacadeFactory.getFacade().deleteAll(users);
		System.out.println("Done.");

		return true;
	}

	private static Reporter createUser(String name, String email,
			String password, boolean admin) {
		Reporter user = new Reporter();
		user.setAdmin(admin);
		user.setName(name);
		user.setEmail(email);
		try {
			user.setPassword(PasswordGenerator.encrypt(password));
		} catch (Exception e) {
			user.setPassword(password);
		}
		return FacadeFactory.getFacade().store(user);
	}

	public static boolean create() {
		System.out.println("===== CREATING DATABASE ========");

		System.out.print("* Creating admin users... ");
		Reporter admin = createUser("admin", "admin@bugrap.com", "admin", true);
		Reporter manager = createUser("manager", "manager@bugrap.com",
				"manager", false);
		Reporter developer = createUser("developer", "developer@bugrap.com",
				"developer", false);
		System.out.println("Done.");

		System.out.print("* Creating projects and versions... ");
		for (int p = 0; p < 5; p++) {
			Project project = new Project();
			project.setManager(manager);
			project.setDevelopers(Collections.singletonList(developer));
			project.setName("Project " + (p + 1));
			project = FacadeUtil.store(project);

			for (int v = 0; v < 3; v++) {
				ProjectVersion version = new ProjectVersion();
				version.setVersion(project.getName() + " - Version " + (v + 1));
				version.setProject(project);
				FacadeUtil.store(version);
			}
		}

		System.out.println("Done.");

		System.out.print("* Creating reports... ");
		List<Report> bugreports = new ArrayList<Report>();
		Random random = new Random(new Date().getTime());
		List<Project> projects = FacadeUtil.getProjects();
		for (int r = 0; r < 100; r++) {
			Project p = projects.get(r % 4);
			List<ProjectVersion> versions = FacadeUtil.getVersions(p);

			Report report = new Report();
			report.setTimestamp(new Date());
			report.setProject(p);
			report.setOccursIn(versions.get(r % 2));

			if (random.nextBoolean()) {
				report.setVersion(FacadeUtil.getVersions(p).get(r % 2));
			}

			ReportType type = random.nextBoolean() ? ReportType.BUG
					: ReportType.FEATURE;
			report.setType(type);

			ReportStatus status = random.nextBoolean() ? ReportStatus.OPEN
					: ReportStatus.CLOSED;
			report.setStatus(status);
			if (status == ReportStatus.CLOSED) {
				report.setResolution(ReportResolution.values()[r % 6]);
			}

			if (type == ReportType.BUG) {
				report.setSummary("Bug report " + random.nextInt(100));
			} else {
				report.setSummary("Feature request " + random.nextInt(100));
			}

			report.setDescription("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. "
					+ "Sed posuere interdum sem. Quisque ligula eros ullamcorper quis, lacinia "
					+ "quis facilisis sed sapien. Mauris varius diam vitae arcu. Sed arcu lectus "
					+ "auctor vitae, consectetuer et venenatis eget velit. Sed augue orci, "
					+ "lacinia eu tincidunt et eleifend nec lacus. Donec ultricies nisl ut felis,"
					+ " suspendisse potenti. Lorem ipsum ligula ut hendrerit mollis, ipsum erat vehicula "
					+ "risus, eu suscipit sem libero nec erat. Aliquam erat volutpat. "
					+ "Sed congue augue vitae neque. Nulla consectetuer porttitor pede. "
					+ "Fusce purus morbi tortor magna condimentum vel, placerat id blandit sit "
					+ "amet tortor.\n\nMauris sed libero. Suspendisse facilisis nulla in lacinia laoreet,"
					+ " lorem velit accumsan velit vel mattis libero nisl et sem. Proin interdum maecenas"
					+ " massa turpis sagittis in, interdum non lobortis vitae massa. Quisque purus lectus, "
					+ "posuere eget imperdiet nec sodales id arcu. Vestibulum elit pede dictum eu, viverra "
					+ "non tincidunt eu ligula.\n\nNam molestie nec tortor. Donec placerat leo sit amet velit."
					+ " Vestibulum id justo ut vitae massa. Proin in dolor mauris consequat aliquam. "
					+ "Donec ipsum, vestibulum ullamcorper venenatis augue. Aliquam tempus nisi in auctor "
					+ "vulputate, erat felis pellentesque augue nec, pellentesque lectus justo nec erat. "
					+ "Aliquam et nisl. Quisque sit amet dolor in justo pretium condimentum.");

			while (random.nextBoolean()) {
				Comment comment = new Comment();
				comment.setAuthor(developer);
				comment.setTimestamp(new Date());
				comment.setComment("Some comment...");
				comment.setType(CommentType.COMMENT);
				comment.setReport(report);

				if (random.nextBoolean()) {
					comment.setType(CommentType.ATTACHMENT);
					comment.setComment("Some attachment...");
					comment.setAttachmentName("text.txt");
					comment.setAttachment("This is some text attachement content"
							.getBytes());
				}
			}

			bugreports.add(report);
		}

		try {
			FacadeFactory.getFacade().storeAll(bugreports);
		} catch (Exception e) {
			System.out.println("Failed!");
			System.out.println(e);
			return false;
		}

		System.out.println("Done.");

		return true;
	}

}
